﻿#include "chinese.h"
#pragma once

#include "shell/shellutils.h"
#include <QComboBox>
#include <QDateTime>
#include <QEvent>
#include <QMutex>
#include <QString>
#include <QTableWidget>
#include <QThreadStorage>
#include <QTranslator>
#include <QTreeWidget>

#define EP_APP_NAME "VPN Client"
#define EP_APP_VERSION "v1.0.0"

constexpr int SECONDS_PER_YEAR = 365 * 24 * 3600;
constexpr int SECONDS_PER_MONTH = 30 * 24 * 3600;
constexpr int SECONDS_PER_DAY = 24 * 3600;
constexpr int SECONDS_PER_HOUR = 3600;
constexpr int SECONDS_PER_MINUTE = 60;

class AppCommon {
public:
    static void closeDialog(QWidget *dialog);
    static QWidget *getRootParent(QWidget *widget);
    static void showWindowToCenter(QWidget *window, QSize size = {}, bool isExec = false);

    /// 提取路径中的最后一部分文件名
    static QString extractFileName(const QString &filePath);

public:
    /// 是否是回环地址
    static bool isLoopbackAddress(const QString &ip);

    /// 从IPV4中取网段信息，默认前面三段是网段
    static QString getNetworkFromIP(const QString &ip);

    // 检查是否是合法的IPv4地址
    static bool isValidIPv4(const QString &ip);

    // 检查是否是合法的网段
    static bool isValidNetwork(const QString &network);

    // 检查IP地址是否包含端口号，如果没有则添加默认端口号8888
    static QString addDefaultPort(const QString &ipPort, const QString &defaultPort);

public:
    /// 检查当前是否开机自启
    static bool checkAutoStart();

    /// 设置是否开机自启
    static bool setAppAutoStart(bool enable);

    /// 系统托盘是否可用
    static bool isSystemTrayAvailable();

    /// 退出程序
    static void exitApp();

    /// 是否本机IP
    static bool isLocalHostUrl(QString url);

    /// 辅助函数：提取字符串中的数字部分，数字前后可能有其他字符
    static QString extractNumericPart(const QString &str);

public:
    /// PMS时间格式
    static const QString PMS_DATE_TIME_FORMAT;

    /// PMS日期格式
    static const QString PMS_DATE_FORMAT;

    /// 解析日期字符串
    static QDateTime parseDateTime(QString time);

    /// 格式化日期，yyyy-MM-dd HH:mm:ss
    static QString formatDateTime(QDateTime time);

    /// 格式化日期，yyyy-MM-dd
    static QString formatDate(QDateTime time);

    /// 将秒值转为一个描述字符串，转为？年？月？日？小时？分钟？秒 这样的格式
    static QString formatSecondTime(int seconds);

    /// 获取开机时刻的时间
    static QDateTime getPCBootTime();

public:
    /// 获取文件的扩展名（小写）
    static QString getFileExtension(QString filePath);

public:
    static bool writeStringToFile(const QString &filePath, const QString &content);

    static bool copyFile(const QString &sourceFilePath, const QString &destinationFilePath);

    /// 检查文件是否存在
    static bool fileExist(const QString &filePath);

    static bool createDir(const QString &dirPath);

    static bool chmodDirTo777(const QString &dirPath);

    static bool chmodFileTo666(const QString &filePath);

    static bool removeDir(const QString &dirPath);

    /// 移除子文件夹，按创建时间删除旧的
    /// \param saveCount 保留几个新的
    static int removeOldSubDir(const QString &dirPath, int saveCount);

    /// 读取子文件夹的名称集合，一般用来提供已下载的数据ID
    static QStringList getSubDirNameList(const QString &dirPath);

    static QString getParentDirPath(const QString &filePath);

    /// 查询所有子文件夹路径
    static QStringList findAllSubDirPath(QString dirPath);

    /// 创建一个临时目录地址
    static QString createTempDirPath();

    /// 搜索第一个文件的路径
    static QString findFirstFileRecursively(const QString &searchDir, const QString &fileName);

    /// 搜索第一个文件类型所在目录路径
    static QString findFirstFileExtRecursively(const QString &searchDir, const QString &fileExt);

    /// 解压压缩包到临时目录
    static ShellUtils::ShellResult extractArchive(const QString &archivePath);

    /// 检查是否是压缩包
    static bool isArchiveFile(const QString &filePath);

    /// 检查是否有指定类型文件
    static bool checkForSpecificFiles(const QString &folderPath, const QString &fileExtension);

public:
    static QStringList getSubFolders(const QString &folderPath);

    /// 提取文件路径中的文件名称
    static QString getFileNameFromFilePath(const QString &fileDirPath);

    /// 是否合法URL
    static bool isValidUrl(const QString &urlString, bool emptyValid = false);

    /// 是否合法IP加端口，如127.0.0.1:8888
    static bool isValidIPPort(const QString &ipPortString);

    // 通过字符串获取整数值
    static int valueForString(const QMap<QString, int> &map, const QString &str);

    // 通过整数获取字符串
    static QString stringForValue(const QMap<QString, int> &map, int value);

public:
    /// 计算文件的MD5
    static QString calculateFileMD5(const QString &filePath);

    /// 确保a中数据全部添加到b中，切在b的最前面
    static void ensureAInFrontOfB(QList<QString> &a, QList<QString> &b);

public:
    static bool isNullOrEmpty(const QString &str);
    static QString getAppCacheRootPath();
    static QString getAppRootPath();
    static QString getAppServiceName();

    /// 是否以root运行
    static bool isRunningAsRoot();

    // 获取当前登录用户名
    static QString getLoginUser();

    /**
     * @brief 使用 getent 命令获取用户 UID
     * @param username 要查询的用户名
     * @return 成功返回 UID，失败返回 -1
     */
    static int getUserIdByGetent(const QString &username);

    static QString getExistingDirectoryAsUser(const QString &caption, const QString &dir, const QStringList &tagDirList = {}, QWidget *parent = nullptr);
};
